﻿using Microsoft.EntityFrameworkCore;
using Routine.Api.DtoParameters;
using RoutineApi.Data;
using RoutineApi.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RoutineApi.Services
{
    public class CompanyRepository : ICompanyRepository
    {
        private readonly RoutineDbContext _context;

        public CompanyRepository(RoutineDbContext routineDbContext)
        {
            _context = routineDbContext ?? throw new AccessViolationException(nameof(routineDbContext));
        }
        public void AddCompany(Company company)
        {
            if (company == null)
            {
                throw new ArgumentNullException(nameof(company));
            }
            company.Id = Guid.NewGuid();
            foreach (var employee in company.Employees)
            {
                employee.Id = Guid.NewGuid();

            }
            _context.Companies.Add(company);
        }

        public void AddEmployeeAsync(Guid companyId, Employee employee)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentException(nameof(companyId));
            }
            if (employee == null)
            {
                throw new ArgumentException(nameof(employee));
            }
            employee.CompanyId = companyId;
            _context.Employees.Add(employee);
        }

        public async Task<bool> CompanyExistsAsync(Guid companyId)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }
            return await _context.Companies.AnyAsync(c => c.Id == companyId);
        }

        public void DeleteCompany(Company company)
        {
            if (company == null)
            {
                throw new ArgumentNullException(nameof(company));
            }
            _context.Companies.Remove(company);
        }

        public void DeleteEmployee(Employee employee)
        {
            _context.Employees.Remove(employee);
        }

        public async Task<IEnumerable<Company>> GetCompaniesAsync(CompanyDtoParameters companyDtoParameters)
        {

            if (companyDtoParameters == null)
            {
                throw new ArgumentException(nameof(companyDtoParameters));
            }
            var queryExpression = _context.Companies as IQueryable<Company>;
            if (!string.IsNullOrWhiteSpace(companyDtoParameters.CompanyName))
            {
                queryExpression = queryExpression.Where(c => c.Name == companyDtoParameters.CompanyName.Trim());

            }
            if (!string.IsNullOrWhiteSpace(companyDtoParameters.SearchTerm))
            {
                queryExpression = queryExpression.Where(c => c.Name.Contains(companyDtoParameters.SearchTerm.Trim()) || c.Introduction.Contains(companyDtoParameters.SearchTerm.Trim()));
            }
            return await queryExpression.ToListAsync();
        }

        public async Task<IEnumerable<Company>> GetCompaniesAsync(IEnumerable<Guid> companyIds)
        {
            if (companyIds == null)
            {
                throw new ArgumentNullException(nameof(companyIds));
            }
            return await _context.Companies.Where(c => companyIds.Contains(c.Id)).OrderBy(x => x.Name).ToListAsync();
        }

        public async Task<Company> GetCompanyAsync(Guid companyId)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }
            return await _context.Companies.FirstOrDefaultAsync(c => c.Id == companyId);
        }

        public async Task<Employee> GetEmployeeAsync(Guid companyId, Guid employeeId)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentException(nameof(companyId));
            }
            if (employeeId == Guid.Empty)
            {
                throw new ArgumentException(nameof(employeeId));
            }
            return await _context.Employees.Where(e => e.CompanyId == companyId && e.Id == employeeId).FirstOrDefaultAsync();
        }

        public async Task<IEnumerable<Employee>> GetEmployeesAsync(Guid companyId, string genderDisplay, string q)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentException(nameof(companyId));
            }
            var items = _context.Employees.Where(c => c.CompanyId == companyId);
            if (string.IsNullOrWhiteSpace(genderDisplay) && string.IsNullOrWhiteSpace(q))
            {
                return await items.OrderBy(e => e.EmployeeNo).ToListAsync();
            }
            if (!string.IsNullOrWhiteSpace(genderDisplay))
            {
                var gender = Enum.Parse<Gender>(genderDisplay.Trim());
                items = items.Where(c => c.Gender == gender);
            }
            if (!string.IsNullOrWhiteSpace(q))
            {
                q = q.Trim();
                items = items.Where(c => c.EmployeeNo.Contains(q) || c.FirstName.Contains(q) || c.LastName.Contains(q));
            }

            return await items.OrderBy(e => e.EmployeeNo).ToListAsync();

        }

        public async Task<bool> SaveAsync()
        {
            return await _context.SaveChangesAsync() >= 0;
        }

        public void UpadteCompany(Company company)
        {
            // throw new NotImplementedException();
        }

        public void UpdateEmployee(Employee employee)
        {
            //throw new NotImplementedException();
        }


    }
}
